package com.zrrd.yunchmall.gateway.filter;

import com.zrrd.yunchmall.gateway.client.AuthServiceClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * @author yekong
 * 在网关中实现统一的权限授权
 * 针对每个请求头或请求参数中的token令牌进行有效性验证，如果有效就完成后续的路由操作，否则返回404错误（无访问权限）
 */
@SuppressWarnings("all")
//第一步：声明一个Filter类，实现GlobalFilter接口
@Service//第三步：将这个注入Spring的bean容器
@ConfigurationProperties("auth-filter")
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    //保证我们自定义的过滤器位于整个过滤器链路的最前端
    @Override
    public int getOrder() {
        return 1;
    }


    @Autowired
    private AuthServiceClient authServiceClient;

    //enabled的赋值：@ConfigurationProperties("auth-filter")该注解会从配置文件中查找auth-filter标签，
    //将标签下的enabled属性赋值给该类中的enabled属性
    private boolean enabled; //设置一个基于配置文件的开关，ture过滤器开启，false过滤器关闭

    //用于存放放行请求，不需要进行鉴权的求情路径集合
    private List<String> excludes;
    public void setExcludes(List<String> excludes) {
        this.excludes = excludes;
    }
    public List<String> getExcludes() {
        return excludes;
    }

    //第二步：重写filter方法
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //当enable为false时，直接跳过过滤器
        if(!enabled) return chain.filter(exchange);

        //请求路径
        String uri = exchange.getRequest().getURI().getPath();
        //如果是包含在放行路径集合里的URI直接通过鉴权环节
        if (excludes.contains(uri)) {
            return  chain.filter(exchange);
        }

        //Authorization请求头中要包含jwt token
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        //1.没找到token 2.token过期 3.token无效
        if(token == null || authServiceClient.auth(token) == null) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();//请求结束，响应客户端
        }else {
            return chain.filter(exchange);//放行
        }

//        return null;
    }
}
